/*
 * sockettcp.cpp
 *
 *  Created on: 22/05/2011
 *      Author: wadi
 */

#include "sockettcp.h"

SocketTcp::SocketTcp(): logger_(log4cxx::Logger::getLogger("common.comm.sockettcp")) {

}

SocketTcp::SocketTcp(struct sockaddr_in adres,int id):Socket(adres,id),logger_(log4cxx::Logger::getLogger("common.comm.sockettcp")){
}

SocketTcp::~SocketTcp() {
}

bool SocketTcp::open() {
    socketId = socket(AF_INET, SOCK_STREAM, 0);
    return (socketId >= 0);
}

void SocketTcp::listenTo(int cantidadConexiones) {
    listen(socketId, cantidadConexiones);
}

SocketTcp* SocketTcp::acceptSocket() {
    SocketTcp* socketAceptado;
    unsigned int idNuevoSocket;
    struct sockaddr_in direCliente;
    unsigned int clilen = sizeof (direCliente);
    idNuevoSocket = accept(socketId, (struct sockaddr*) &direCliente, &clilen);
    if (!closed && idNuevoSocket > 0) {
        socketAceptado = new SocketTcp(direCliente, idNuevoSocket);
        return socketAceptado;
    }
    return NULL;
}

bool SocketTcp::bindTo(int puerto) {
    struct sockaddr_in sa;
    memset((char*) &sa, 0, sizeof (sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(puerto);
    sa.sin_addr.s_addr = INADDR_ANY;

    int r = bind(socketId, (struct sockaddr*) &sa, (socklen_t)sizeof (struct sockaddr));
    return r >= 0;
}

int SocketTcp::recibir(unsigned char * buffer, int cantidad) {
    int caracteresLeidos = recv(socketId, buffer, cantidad, 0);
    LOG4CXX_TRACE(logger_, "Leidos caracteres  " << caracteresLeidos);
    // Se cerro la conexión donde estaba recibiendo o tiro algún error
    if(caracteresLeidos<=0){
        LOG4CXX_TRACE(logger_, "Cerrando  " << caracteresLeidos);
        closed=true;
    }

    return caracteresLeidos;
}

int SocketTcp::escribir(char * buffer, int cantidad) {
    int enviadosTotales=0;
    int enviados=0;
    while(enviadosTotales<cantidad){
    enviados=write(socketId, buffer+enviados, cantidad-enviadosTotales);
    if(enviados<0)
        return -1;
    enviadosTotales+=enviados;
    }
    LOG4CXX_TRACE(logger_, "Enviados:  " << enviadosTotales <<" de " << cantidad);
    return enviadosTotales;

}

bool SocketTcp::connectTo(std::string url, int port) {
    struct sockaddr_in sa;
    memset((char*) &sa, 0, sizeof (sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(port);
    struct hostent* he = gethostbyname(url.c_str());
    if (he == NULL)
        return false;
    sa.sin_addr = *((struct in_addr*) he->h_addr);
    memset(&(sa.sin_zero), 8, sizeof (int));
    return connect(socketId, (struct sockaddr*) &sa, sizeof (struct sockaddr)) != -1;
}
